﻿using HRX.PayCenter.Contract;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HRX.PayCenter.ApplicationCore.Exceptions;
using HRX.PayCenter.ApplicationCore.Interfaces;
using System.IO;
using HRX.PayCenter.Web.Extensions;

namespace HRX.PayCenter.Web.Middlewares
{
    /// <summary>
    /// 全局处理
    /// </summary>
    public class GlobalHandlingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IAppLogger<GlobalHandlingMiddleware> _logger;
        private string responseContent = string.Empty;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        /// <param name="logger"></param>
        public GlobalHandlingMiddleware(RequestDelegate next, 
            IAppLogger<GlobalHandlingMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        /// <summary>
        /// 中间层
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            //_logger.LogInformation(null, $"【全局记录】请求体：{context.Request.Query.QueryStr()}");
            MemoryStream ms = null;
            Stream orgBodyStream = null;
            try
            {
                ms = new MemoryStream();
                orgBodyStream = context.Response.Body;

                context.Response.Body = ms;

                await _next(context);

                using (var sr = new StreamReader(ms))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    responseContent = sr.ReadToEnd();

                    ms.Seek(0, SeekOrigin.Begin);
                    await ms.CopyToAsync(orgBodyStream);
                    context.Response.Body = orgBodyStream;
                }
            }
            catch (Exception e)
            {
                if (context.Response.ContentType == null)
                {
                    context.Response.ContentType = "application/json;charset=utf-8";
                }
                _logger.LogError(e, e.Message);

                var message = e.Message;
                ResultSet<string> data = null;
                if (e is PayCenterException)
                {
                    data = ResultSet<string>.Fail((e as PayCenterException).Code, message);
                } //业务code
                else
                {
                    data = ResultSet<string>.SysException(e.Message);
                }

                responseContent = JsonConvert.SerializeObject(data);
                byte[] bodyArray = System.Text.Encoding.UTF8.GetBytes(responseContent);
                long len = bodyArray.Length;
                ms.Seek(0, SeekOrigin.Begin);
                ms.SetLength(len);
                await ms.WriteAsync(bodyArray, 0, Convert.ToInt32(len));
                ms.Seek(0, SeekOrigin.Begin);
                await ms.CopyToAsync(orgBodyStream);
                context.Response.Body = orgBodyStream;
            } //异常重写
            finally
            {
                if (ms != null)
                {
                    ms.Dispose();
                }

                if (orgBodyStream != null)
                {
                    orgBodyStream.Dispose();
                }
                //记录请求和结果
                _logger.LogInformation(null, $"【全局记录】响应体：{responseContent}");
            }
        }

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="context"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task HandleExceptionAsync(HttpContext context, ResultSet<string> data)
        {
            responseContent = JsonConvert.SerializeObject(data);
            context.Response.ContentType = "application/json;charset=utf-8";
            await context.Response.WriteAsync(responseContent);
        }
    }
}
